package org.example.springsecurity_.filter;

import io.jsonwebtoken.*;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.example.springsecurity_.Impl.UserServiceImpl;
import org.example.springsecurity_.domain.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import java.util.ArrayList;

@Component
public class JwtFilter extends OncePerRequestFilter {
    @Autowired
    private UserServiceImpl userServiceImpl;
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String requestURI=request.getRequestURI();
        if(!requestURI.startsWith("/api")){
            filterChain.doFilter(request,response);
            return;
        }
        // 1.从请求头中获取前端传过来的token
        String token=resolverToken(request);
//        System.out.println("token:"+token);
        if(token!=null && validateToken(token)){
            //2.从token中拿东西
            Claims body=claimsJws(token).getBody();
            String sub = (String) body.get("sub");
            String username = (String) body.get("username");
            System.out.println("用户id:"+sub+",");
            System.out.println("username:"+username);

            User user =(User) redisTemplate.opsForValue().get("login:" + username);
            System.out.println("过滤器中的user"+user);
            if(user != null){
                // 3.得到用户信息UserDetails
                UserDetails userDetails = userServiceImpl.loadUserByUsername(username);
                // 4.生产UsernamePasswordAuthenticationToken（这个相当于凭证,放行的门票）
                UsernamePasswordAuthenticationToken authenticationToken=new UsernamePasswordAuthenticationToken(userDetails,null,userDetails.getAuthorities());
                // 5.把凭证放到放到SecurityContextHolder的环境中去（这样做的目的在于后续过滤器放行）
                SecurityContextHolder.getContext().setAuthentication(authenticationToken);
            }
        }
        // 此过滤器基本执行完毕，放行到下一个过滤器
        filterChain.doFilter(request,response);
    }
    //请求头中解析token
    private String resolverToken(HttpServletRequest request){
        String authorization = request.getHeader("Authorization");
        if(authorization!=null && authorization.startsWith("Bearer ")){
            return authorization.substring(7);
        }
        return null;
    }
    // 验证token是否有效
    private boolean validateToken(String token){
        try {
            //不报错说明有效
            Jwts.parser().setSigningKey(String.valueOf(SignatureAlgorithm.HS256)).parseClaimsJws(token);
            return true;
        }catch (Exception e){
            e.printStackTrace();
            return false;
        }
    }
    // 从token中获取subject
    private Jws<Claims> claimsJws(String token){
        Jws<Claims> claimsJws =Jwts.parser().setSigningKey(String.valueOf(SignatureAlgorithm.HS256)).parseClaimsJws(token);
        return claimsJws;
    }
}
